﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.Web.Http;
using System.Web.Http.ModelBinding;
using System.Web.Security;
using System.Xml.Linq;
using XData.Data.Services;

namespace XData.WebApp.Models
{
    public static class WebSecurity
    {
        private static AccountService AccountService
        {
            get { return new AccountService(); }
        }

        public static XElement User
        {
            get
            {
                if (HttpContext.Current.User.Identity.IsAuthenticated)
                {
                    return AccountService.GetUser(HttpContext.Current.User.Identity.Name);
                }
                return null;
            }
        }

        public static bool Login(LoginModel model)
        {
            if (AccountService.Validate(model.UserName, model.Password))
            {
                FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe);
                return true;
            }
            return false;
        }

        public static void Logout()
        {
            FormsAuthentication.SignOut();
        }

        private const string Api_Verification_Token_Name = "__ApiVerificationToken";

        public static HttpResponseMessage GetApiVerificationToken()
        {
            string apiVerificationToken = AccountService.GenerateApiVerificationToken();
            string encrypted = AccountService.EncryptApiVerificationToken(apiVerificationToken);

            HttpResponseMessage response = new HttpResponseMessage();
            string content = new XElement(Api_Verification_Token_Name, apiVerificationToken).ToString();
            response.Content = new StringContent(content, System.Text.Encoding.UTF8, "application/xml");

            CookieHeaderValue cookie = new CookieHeaderValue(Api_Verification_Token_Name, encrypted);
            response.Headers.AddCookies(new CookieHeaderValue[] { cookie });
            return response;
        }

        public static HttpResponseMessage Login(XElement value)
        {
            bool result;
            string userName = value.Element("UserName").Value;
            string password = value.Element("Password").Value;
            bool rememberMe = bool.Parse(value.Element("RememberMe").Value);
            if (AccountService.Validate(userName, password))
            {
                FormsAuthentication.SetAuthCookie(userName, rememberMe);
                result = true;
            }
            else
            {
                result = false;
            }

            HttpResponseMessage response = new HttpResponseMessage();
            string content = new XElement("Login", result.ToString()).ToString();
            response.Content = new StringContent(content, System.Text.Encoding.UTF8, "application/xml");

            CookieHeaderValue cookie = new CookieHeaderValue(Api_Verification_Token_Name, string.Empty);
            cookie.MaxAge = TimeSpan.Zero;
            response.Headers.AddCookies(new CookieHeaderValue[] { cookie });
            return response;
        }

        public static void ValidateApiVerificationToken(HttpRequestMessage request, XElement value)
        {
            try
            {
                string apiVerificationToken = value.Element(Api_Verification_Token_Name).Value;
                string encrypted = AccountService.EncryptApiVerificationToken(apiVerificationToken);
                string cookie = request.Headers.GetCookies("__ApiVerificationToken").First()["__ApiVerificationToken"].Value;
                if (encrypted == cookie) return;
                throw new Exception();
            }
            catch
            {
                throw new Exception("A required anti-forgery token was not supplied or was invalid.");
            }
        }

        public static bool ChangePassword(ChangePasswordModel model)
        {
            string userName = HttpContext.Current.User.Identity.Name;
            string password = model.OldPassword;
            if (!AccountService.Validate(userName, password)) return false;
            AccountService.SetPassword(userName, model.NewPassword);
            return true;
        }

        public static HttpResponseMessage ChangePassword(XElement value, ApiController apiController)
        {
            ChangePasswordModel model = new ChangePasswordModel()
            {
                OldPassword = value.Element("OldPassword").Value,
                NewPassword = value.Element("NewPassword").Value,
                ConfirmPassword = value.Element("ConfirmPassword").Value
            };
            apiController.Validate(model);
            ModelStateDictionary modelState = apiController.ModelState;
            if (modelState.IsValid)
            {
                bool result = WebSecurity.ChangePassword(model);
                HttpResponseMessage response = new HttpResponseMessage();
                string content = new XElement("ChangePassword", result.ToString()).ToString();
                response.Content = new StringContent(content, System.Text.Encoding.UTF8, "application/xml");
                return response;
            }
            throw modelState.GetElementValidationException(value);
        }


    }
}